/**
 * @file{同步 偏贴工站库}
 */
 'use strict';

 const LRU = require("lru-cache");
 const schedule = require('node-schedule');
 const {initFlawData} = require('../../model/piantie/flaw');
 const {initFlawFilterData} = require('../../model/piantie/flaw_filter');
 const {initJobData} = require('../../model/piantie/job');
 const {initPanelData} = require('../../model/piantie/panel');
 const {transformData} = require('../../uitls/tool');
 const options = {
    max: 500,
    length: function (n, key) { return n * 2 + key.length },
    dispose: function (key, n) { n.close() },
    maxAge: 1000 * 60 * 60
 }
 /**
  * 同步精度检测工站数据父类
  */
 class PiantieBase {

    flawFilterDataArr = []

    constructor (tableModel, sequelize_source, sequelize_aim, stationName, mujian) {
        //各个表的操作模型对象
        this.cache = new LRU(options);
        this.PanelPiantie = tableModel.PanelPiantie;
        this.FlawFilterPiantie = tableModel.FlawFilterPiantie;
        this.FlawPiantie = tableModel.FlawPiantie;
        this.JobPiantie = tableModel.JobPiantie;
        this.mujian = mujian;

        this.sequelize_source = sequelize_source;
        this.sequelize_aim = sequelize_aim;
        this.stationName = stationName;
        // 初始化各个表
        initFlawData(this.sequelize_aim);
        initFlawFilterData(this.sequelize_aim);
        initJobData(this.sequelize_aim);
        initPanelData(this.sequelize_aim);
        // 查询当前同步的位置
        this.getSyncPosition();
        // 开始定时缓存任务
        let job = schedule.scheduleJob('*/2 * * * * *', () => {
            this.handPanelInfo(); // panel
            this.handJobInfo(); // job
            this.handFlawInfo(); // Flaw
            this.handFlawFilterinfo(); // flaw_filter
        })
    }
    /**
     * 获取当各表同步的位置
     */
    async getSyncPosition () {
        this.panelUid = await this.getMaxUidfromAimLibrary('panel');
        this.jobUid = await this.getMaxUidfromAimLibrary('job');
        this.jobUid =  this.jobUid ?  this.jobUid : 1;
        this.flawUid = await this.getMaxUidfromAimLibrary('flaw');
        // 由于缺陷分类的信息在doff表中，所以缺陷分类的id和doff的uid保持一致
        this.FlawFilterId = await this.getMaxUidfromAimLibrary('flaw_filter');
        // 缺陷分类的id与panelUid保持一致
        this.flawFilterUid = this.panelUid ? this.panelUid : 1;
    }
    /**
     * 获取最新同步的位置
     * @param {String} tableName 表名
     * @return 同步的最新uid
     */
    async getMaxUidfromAimLibrary(tableName) {
        switch (tableName) {
            case 'panel':
                return this.PanelPiantie.getLatestPanelId(this.sequelize_aim);
            case 'job':
                return this.JobPiantie.getLatestJobId(this.sequelize_aim);
            case 'flaw':
                return this.FlawPiantie.getLatestFlawId(this.sequelize_aim);
            case 'flaw_filter':
                return this.FlawFilterPiantie.getLatestFlawFilterId(this.sequelize_aim, this.panelUid ? this.panelUid : 1);
            default:
                return null;
        }
    }
    /**
     * hand flaw_filter
     */
    async handFlawFilterinfo (panelId) {
        if (panelId) {
            let res = await this.FlawFilterPiantie.getFlawFilterInfoByDoffUid(this.sequelize_source, panelId);
            this.handTranformData(JSON.parse(res));
            let flawFilterCount = await this.FlawFilterPiantie.getFlawCountByPanel(this.sequelize_source, panelId);
            let map = transformData(flawFilterCount);
            let flawFilterArray = [];
            for (const i of map) {
                flawFilterArray.push(i[1]);
            }
            let resultData = [];
            flawFilterArray.forEach( dataItem => {
                this.flawFilterDataArr.forEach(typeItem => {
                    if (Number(dataItem.flaw_class_type) == typeItem.id) {
                        resultData.push({
                            ...dataItem,
                            color: typeItem.color,
                            show: typeItem.show,
                            symbol: typeItem.symbol,
                            shape: typeItem.shape
                        })
                    }
                })
            })
            this.flawFilterDataArr = [];
            return resultData;
        }
        // flaw表的最新的doff_id --> panel_uid
        let maxPanelUid = await this.FlawFilterPiantie.getMaxDoffUid(this.sequelize_source);
        // 确保源库panel更新完了
        if (this.flawFilterUid < maxPanelUid) {
            // 插叙缺陷类型json
            let res = await this.FlawFilterPiantie.getFlawFilterInfoByDoffUid(this.sequelize_source, this.flawFilterUid ? this.flawFilterUid : 1);
            if(res) {
                // 整理缺陷类型
                this.handTranformData(JSON.parse(res));
                // console.log(this.flawFilterDataArr);
                //查询这片上面的所有缺陷
                let flawFilterCount = await this.FlawFilterPiantie.getFlawCountByPanel(this.sequelize_source, this.flawFilterUid ? this.flawFilterUid : 1);
                // 统计转换
                let map = transformData(flawFilterCount);
                let flawFilterArray = []
                // flawFilter ID开始的位置
                let maxFlawFilterId = this.FlawFilterId !== null ? this.FlawFilterId : await this.FlawFilterPiantie.getLatestFlawFilterId(this.sequelize_aim);
                let index = 1
                for (const i of map) {
                    flawFilterArray.push({
                        ...i[1],
                        id: maxFlawFilterId + index
                    })
                    index++;
                }
                // 遍历所有缺陷分类，加上color， show， symbol三个属性
                let resultData = [];
                flawFilterArray.forEach( dataItem => {
                    this.flawFilterDataArr.forEach(typeItem => {
                        if (Number(dataItem.flaw_class_type) == typeItem.id) {
                            resultData.push({
                                ...dataItem,
                                color: typeItem.color,
                                show: typeItem.show,
                                symbol: typeItem.symbol,
                                shape: typeItem.shape
                            })
                        }
                    })
                })
                //post到汇总库
                this.mujian.updateFlawFilterInfo(resultData);
                console.log(`" **${this.stationName}** " 的flaw数据已经上传完毕，flaw_flilter统计完成，马上post到目标库`);
                //post目标库
                this.postDataToLineDb(this.FlawFilterPiantie, resultData, 'flaw_filter');
                this.flawFilterUid++;
                this.FlawFilterId = null;
                this.flawFilterDataArr = [];
            } else {
                console.log('无此panel缺席类型信息');
            }
        } else {
            console.log(`" **${this.stationName}** " 的flaw数据还没上传完，将会继续Loop`);
        }
    }
    /**
     * 解析缺陷信息
     * @param {Object} data 代转换的对象
     */
    handTranformData (data) {
        for (const key in data) {
            if (key === 'Attributes') {
                this.flawFilterDataArr.push({
                    show: data[key].show,
                    symbol: data[key].symbol,
                    color: data[key].color,
                    id: data[key].id,
                    shape: data[key].shape
                });
            }
            if (key !== 'Attributes' && Object.prototype.toString.call(data[key]) === '[object Object]') {
                this.handTranformData(data[key]);
            }
        }
    }
    /**
     * hand  Flaw
     */
    async handFlawInfo (panelId) {
        if (panelId) {
            let res = await this.FlawPiantie.getFlawData(this.sequelize_source, panelId);
            return res;
        }
        let res = await this.FlawPiantie.getFlawData(this.sequelize_source, this.flawUid ? this.flawUid : 0);
        if (res.length) {
            // 更新当前同步的位置
            this.flawUid = res[res.length - 1].uid;
            // 汇总到汇总库
            this.mujian.updateFLawInfo(res);
            //post目标库
            this.postDataToLineDb(this.FlawPiantie, res, 'flaw');
        } else {
            console.log(`" **${this.stationName}** " Flaw表已是最新`);
        }
    }
    /**
     * hand job
     * @param {String} panelId
     */
    async handJobInfo (panelId) {
        if (panelId) {
            let jobInfo = await this.JobPiantie.getJobInfoByPanelId(this.sequelize_source, panelId);
            if (!jobInfo) return [];
            return {
                ...jobInfo,
                start_time_str: jobInfo.start_time.toString(),
                finish_time_str: jobInfo.finish_time.toString()
            };
        }
        // 保证job下的所有doff都存再去同步job
        let res = await this.JobPiantie.getJobInfoByPanelId(this.sequelize_source, this.jobUid);
        if (res) {
            let jobData = {
                ...res,
                start_time_str: res.start_time.toString(),
                finish_time_str: res.finish_time.toString()
            }
            // post目标库
            this.postDataToLineDb(this.JobPiantie, jobData, 'job');
            // 查询doff表的max(jobId)
            let maxJobUid = await this.JobPiantie.getMaxJobIdFromSource(this.sequelize_source);
            // 更新当前同步位置
            this.jobUid < maxJobUid ? this.jobUid ++ : '';
        } else {
            console.log(`" **${this.stationName}** " 没查到job信息!`);
        }
    }
    /**
     * hand panel
     * @param {String} panelId
     */
    async handPanelInfo (panelId) {
        // 通过panel_id查
        if (panelId) {
            let panelInfo = await this.PanelPiantie.findLatestPanelInfo(this.sequelize_source, panelId);
            // 缓存不需要这个数据
            delete panelInfo.detectParam;
            return this.shakePanelInfo(panelInfo);
        }
        // 查询doff表的max(jobId)
        let panelInfo = await this.PanelPiantie.findLatestPanelInfo(this.sequelize_source, this.panelUid ? this.panelUid: 1);
        if (panelInfo) {
            // 格式转换
            let panelInfoFormat = this.shakePanelInfo(panelInfo);
            // 汇总到汇总库
            this.mujian.updatePanelInfo(panelInfoFormat);
            // post目标库
            this.postDataToLineDb(this.PanelPiantie, panelInfoFormat, 'panel');
            // 查源库的panel最新的更新位置
            let maxPanelUid = await this.PanelPiantie.getLatestPanelFromSource(this.sequelize_source);
            this.panelUid < maxPanelUid ? this.panelUid++ : '';
        } else {
            console.log(`" **${this.stationName}** " Panel表已是最新`);
        }
    }
    /**
     * panel的数据格式转换逻辑
     * @param {*} panelInfo 
     * @returns 
     */
    shakePanelInfo (panelInfo) {
        let exConfig1 = JSON.parse(panelInfo.exConfig1)
        if (exConfig1) {
            let modelSize = exConfig1.job.modelSize.value;
            let length_cd = modelSize.slice(0, modelSize.search(/;/));
            let length_md = modelSize.slice(modelSize.search(/;/) + 1, modelSize.length);
            let panelInfoFormat = {
                ...panelInfo,
                length_md,
                length_cd,
                gen_time_str: panelInfo.gen_time.toString(),
                is_ok: panelInfo.flaw_count > 0 ? 1 : 0,
                checked: false
            }
            delete panelInfoFormat.exConfig1;
            return panelInfoFormat;
        } else {
            console.log(`**${this.stationName}**源库panel表缺少exConfig1字段信息,无法统计缺陷长度宽度信息`);
            let panelInfoFormat = {
                ...panelInfo,
                gen_time_str: panelInfo.gen_time.toString(),
                is_ok: panelInfo.flaw_count > 0 ? 1 : 0,
                checked: false
            }
            delete panelInfoFormat.exConfig1;
            return panelInfoFormat;
        }
    }
    /**
     * 上传data到产线db的指定表中
     * @param {} operatorName 表的操作对象
     * @param {Object} data 上传的数据
     * @param {String} tableName 表名
     */
     async postDataToLineDb (operatorName, data, tableName) {
        // 存进目标库
        try {
            let res = await operatorName.uploadPolInfo(data);
            if(res.dataValues || res.length) {
                console.log(`${tableName}上传**${this.stationName}**库sucess!`);
            }else {
                console.log(`${tableName}上传**${this.stationName}**库的数据为空`);
            }
        } catch (error) {
            // console.log(error);
            console.log(`${tableName}上传**${this.stationName}**库failed`);
        }
    }
 }

 module.exports = PiantieBase;